#ifndef __OBSERVERS_H__
#define __OBSERVERS_H__

#include <list>
#include <map>
#include <string>

class IParam
{
public:
	virtual ~IParam() {}
};

template< class T >
class Param : public IParam
{
public:
	Param( const T& p ) : value( p ) {}
	T	value;
};

class IObserver
{
public:
	virtual void operator () ( IParam* param ) = 0;
	virtual void execute( IParam* param ) = 0;
	virtual ~IObserver() {};
};

template < class T >
class Observer : public IObserver
{
	typedef void ( T::*Func )( IParam* );
public:

	Observer( T* type, Func func ) : _type( type ), _func( func ) {}
	~Observer() {}
	
	bool operator == ( Observer< T >& observer )
	{
		return ( observer._type == _type && observer._func == _func ) ? true : false;
	}

	void operator () ( IParam* param )
	{
		( _type->*_func )( param );
	}
	
	void execute( IParam* param )
	{
		this->operator()( param );
	}

	T* type() { return _type; }
	
	Func* func() { return _func; }

private:
	T*			_type;
	Func		_func;
};

class Observers	
{
public:
	
	Observers( ) { };
	
	~Observers() 
	{
		removeObservers();
	};

	template < class T >
	bool addObserver( T* type, typename Observer< T >::Func func )
	{
		Observer< T >* obr = new Observer< T >( type, func );

		for ( std::list< IObserver* >::iterator it = _observers.begin(); it != _observers.end(); ++it )
		{
			if ( *obr == *( ( Observer< T >* )*it ) )
			{
				return false;
			}
		}
		
		_observers.push_back( obr );
		
		return true;
	}

	template < class T >
	bool removeObserver( T* type, typename Observer< T >::Func func )
	{
		Observer< T >* obr = new Observer< T >( type, func );

		for ( std::list< IObserver* >::iterator it = _observers.begin(); it != _observers.end(); ++it )
		{
			if ( *obr == *( ( Observer< T >* )*it ) )
			{
				_observers.erase( it );
				return true;
			}
		}
		return false;
	}

	void removeObservers()
	{
		for ( std::list< IObserver* >::iterator it = _observers.begin(); it != _observers.end(); ++it )
		{
			delete *it;
		}
		_observers.clear( );
	}

	void operator () ( IParam* param )
	{
		for ( std::list< IObserver* >::iterator it = _observers.begin(); it != _observers.end(); ++it )
		{
			( *( *it ) )( param );
		}
	}

	void execute( IParam* param )
	{
		this->operator()( param );
	}

private:
	std::list< IObserver* >	_observers;
};

#endif